home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d20 / makearc3.arc / MAKEARC.C < prev    next >
Text File  |  1990-12-04  |  37KB  |  1,288 lines

  1.  
  2. /* MakeArc copyright (c) 1990 by M. Kimes -- All Rights Reserved    */
  3. /* Version 2.04   You can use this freely.  Check with me before    */
  4. /* releasing modified executables or source, please (I'll probably  */
  5. /* allow it).  Exceptions:  Strict translation to foreign languages */
  6. /* and ports to other platforms (non-IBMPC-compatible)--go for it.  */
  7. /* Corrections, bug reports, etc. welcome.  Flames ignored by a     */
  8. /* master.                                                          */
  9.  
  10.  
  11. /* Include files; a couple of TC specific here... */
  12.  
  13. #include <conio.h>
  14. #include <dir.h>
  15. #include <time.h>
  16. #include <dos.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <io.h>
  20. #include <fcntl.h>
  21. #include <ctype.h>
  22. #include <process.h>
  23. #include <string.h>
  24.  
  25. /* Couple of typedefs */
  26.  
  27. typedef unsigned int word;
  28. typedef unsigned     bit;
  29.  
  30. /* Message header */
  31.  
  32. struct _msg {
  33.   char from[36];
  34.   char to[36];
  35.   char subj[72];
  36.   char date[20];        /* <--Did you notice the length of that? */
  37.   word times;
  38.   word dest;
  39.   word orig;
  40.   word cost;
  41.   word orig_net;
  42.   word dest_net;
  43.   int  msg_filler[4];    /* Differs by implementation; the heck with it */
  44.   word reply;
  45.   word attr;
  46.   word up;
  47. };
  48.  
  49. /* Message attributes */
  50.  
  51. #define MSGPRIVATE 0x0001
  52. #define MSGCRASH   0x0002
  53. #define MSGREAD    0x0004
  54. #define MSGSENT    0x0008
  55. #define MSGFILE    0x0010
  56. #define MSGFWD     0x0020
  57. #define MSGORPHAN  0x0040
  58. #define MSGKILL    0x0080
  59. #define MSGLOCAL   0x0100
  60. #define MSGXX1     0x0200
  61. #define MSGXX2     0x0400
  62. #define MSGFRQ     0x0800
  63. #define MSGRRQ     0x1000
  64. #define MSGCPT     0x2000
  65. #define MSGARQ     0x4000
  66. #define MSGURQ     0x8000
  67.  
  68. /* Packet header */
  69.  
  70. struct _pkthdr {               /* Mostly copied from JoHo.  I like JoHo. */
  71.     word
  72.         orig_node,             /* originating node */
  73.         dest_node,             /* destination node */
  74.         year,                  /* 1989 - nnnnn */
  75.         month,                   /* 1-12 (note all this wasted space!) */
  76.         day,                   /* 1-31 */
  77.         hour,                   /* 0-23 */
  78.         minute,                   /* 0-59 */
  79.         second,                   /* 0-60 */
  80.         rate,                  /* unused */
  81.         ver,                   /* always 2 */
  82.         orig_net,              /* originating net */
  83.         dest_net;              /* destination net */
  84.     char
  85.         product,               /* product code */
  86.         rev_lev,               /* revision level */
  87.         password[8];
  88.     word
  89.         qm_orig_zone,          /* BARF! */
  90.         qm_dest_zone;           /* BARF! */
  91.     char TRASH[8];               /* Domain? */
  92.     word
  93.         orig_zone,             /* originating zone */
  94.         dest_zone,             /* destination zone */
  95.         orig_point,            /* originating point */
  96.         dest_point;            /* destination point */
  97.     long pr_data;
  98. };
  99.  
  100. /* Global flags and variables, w/ defaults */
  101.  
  102. char msgattach=0;                /* Make *.MSG attaches? */
  103. word myzone=0;                    /* For our address */
  104. word mynet=0;                    /* " */
  105. word mynode=0;                    /* " */
  106. word mypoint=0;                    /* " */
  107. char configfile[133]="MAKEARC.CFG";    /* Config file to read */
  108. char root[128]="";                /* 'Root' outbound dir */
  109. char outbound[133]="";            /* Extended outbound dir */
  110. char netdir[128]="";            /* Net msg directory if *.MSG attaches */
  111. char arccmd[133]="";            /* Default archive command */
  112. char alltype='N';                /* Default mail type */
  113. char didbreak=0;                /* CTRL-BREAK flag */
  114. char schedtag[128]="";            /* Schedule tag */
  115. word lines=0;                    /* For debug info */
  116. char debug=0;                    /* debug on? */
  117. char more=0;                    /* more on? */
  118. char usingbink=0;                /* Use BINKLEY.CFG? */
  119. word rzone=0;                    /* For routing */
  120. word rnet=0;                    /* " */
  121. word rnode=0;                    /* " */
  122. word rpoint=0;                    /* " */
  123.  
  124. /* Function definitions */
  125.  
  126. char     pascal spawnit (char *a);
  127. char     pascal check_4flo (word zone,word net,word node,word point);
  128. char *   pascal stristr (char *t, char *s);
  129. void     cdecl  deinit(void);
  130. void     pascal say_error (long lastpos,FILE *fp);
  131. int      pascal makearc (char *arcfile,char *pktfile,char *origpkt,char *outbound);
  132. word     pascal makeflo(word zone,word net,word node,word point,char *sendfile,char type);
  133. word     pascal makemessage (word zone,word net,word node,word point,char *sendfile,char type);
  134. void     pascal next_name(char *);
  135. void     pascal make_poll (char *line,long lastpos,FILE *fp);
  136. FILE *   pascal analyze(char *);
  137. char *   pascal arcname(word,word);
  138. char *   pascal filename(word,word);
  139. char *   pascal fidodate(void);
  140. char *   pascal lstrip(char *);
  141. char *   pascal rstrip(char *);
  142. char *   pascal stripcr(char *);
  143. int      cdecl  break_handler(void);
  144. void     pascal moveit (struct ffblk *f, char *myoutbound, char *outbound, char type, char archive,word net,word node,word fromzone);
  145. void     pascal move_prep(char *line,long lastpos,FILE *fp);
  146. void     pascal change_mail(char *line,long lastpos,FILE *fp);
  147. long     pascal make_msgid(void);
  148. char *   pascal find_sched(FILE *fp,char *schedtag,int wholefile);
  149. char *   pascal skip_white(char *);
  150. char *   pascal skip_nonwhite(char *);
  151. char *   pascal to_delim(char *,char *);
  152. int      cdecl hardware_error (int errnum,int ax,int bp,int si);
  153.  
  154. /* ID stuff */
  155.  
  156. #define MAKEVER "2.04"
  157.  
  158. #define PID_ID "MA 2.04"
  159.  
  160. #define BETA
  161.  
  162. /* Increase stack size */
  163.  
  164. extern unsigned _Cdecl _stklen = 8192;
  165.  
  166.  
  167.  
  168.  
  169. void cdecl main (int argc,char *argv[]) {
  170.  
  171.     FILE     *fp;
  172.     struct  ffblk f,d;
  173.     time_t  t,starttime;
  174.     char     s[133],s2[133],pktfile[133],arcfile[133],origpkt[13];
  175.     word     hisnode,hisnet,hiszone=0,hispoint=0;
  176.     char     *p,*pp;
  177.     char     new,type=0,lastlevel=0;
  178.     char     temp[34];
  179.     long     t_counter=0,lastpos;
  180.     char     tempcmd[80]="";
  181.     char     doingnet,doingdomain,doingzone;
  182.     int      founddir,rc;
  183.  
  184.   /* Big, ugly main() function.  What do you expect from an amateur ex-BASIC
  185.      programmer, anyway? */
  186.  
  187.   starttime=time(NULL);  /* For length-of-run timer */
  188.  
  189.   /* Display program title and copyright info */
  190.  
  191.   fprintf(stderr,"\n\nMAKEARC v%s  %s  %s   copyright (c) 1990 by M. Kimes",
  192.     MAKEVER,__DATE__,__TIME__);
  193.  
  194. #ifdef BETA
  195.   fprintf(stderr," -- Beta");
  196. #endif
  197.  
  198.   fprintf(stderr,"\n");
  199.  
  200.   /* Nothing on command line--let 'em know help is available. */
  201.  
  202.   if(argc==1) fprintf(stderr,"I archive packets and make attaches for them.  ? for help.\n");
  203.  
  204.   /* First arg is ? so give 'em the help and stop */
  205.  
  206.   if(argc>1 && *argv[1]=='?') {
  207.         fprintf(stderr,"\nGimme a config file, default MAKEARC.CFG.  A schedule tag is optional.\n"
  208.                "If environment variable MAKECFG is set, I'll use that value to find the config\n"
  209.                "file instead.  If MAKESCHD is set, I'll use that value for a schedule tag.\n"
  210.                "Examples: (assumes environment variables not used)\n"
  211.                "MAKEARC (defaults to MAKEARC.CFG, no schedule tag)\n"
  212.                "MAKEARC ALTMAKE.CFG (defaults to no schedule tag)\n"
  213.                "MAKEARC MAKEARC2.CFG MAILTIME (config file MAKEARC2.CFG, schedule tag MAILTIME)\n"
  214.                "MAKEARC MAKEIT.CFG AFTERMAIL ! (startup with debug on)\n"
  215.                "MAKEARC MAKE2.CFG BEFOREMAIL ? (startup with more info on)\n"
  216.                "\nYou probably shouldn't use points *at all* when dealing with the outbound.\n"
  217.                "You should not route Crash mail.\n\n"
  218.                "In the configuration file, list the following:\n"
  219.                "SCHED <any_text> (A schedule tag, not required unless you use them)\n"
  220.                "ADDRESS <zone:net/node[.point]> (Your address--use point only if\n"
  221.                "                                 your mailer understands it)\n"
  222.                "OUTBOUND <main outbound directory>\n"
  223.                "NETDIR <netmail directory> (use with MSG below)\n"
  224.                "MSG (means create *.MSG attaches instead of *.FLO attaches)\n"
  225.                "FLO (opposite of MSG, default)\n"
  226.                " [Any Key]");
  227.                getch();
  228.                fprintf(stderr,"\b\b\b\b\b\b\b\b\b\b"
  229.                "ARCCMD <default archive command>\n"
  230.                "ALLTYPE <default mail type: Crash, Hold, etc.>\n"
  231.                "ROUTE <address> (routes all following mail to <address> until\n"
  232.                "                 next ROUTE command (ROUTE 0:0/0 cancels))\n"
  233.                "DOMAIN <main outbound dir> <type> <arc cmd>\n"
  234.                " (Do a pass through outbound directories.  Arguments are optional.\n"
  235.                "  Defaults will be used if not present.  Note that giving an outbound\n"
  236.                "  directory here performs an implicit OUTBOUND command)\n"
  237.                "ZONE <zone#>: <mail type> <arc cmd> (Do a pass through <zone#>)\n"
  238.                "NET <zone#>:<net#>/ <mail type> <arc cmd> (do a pass through <net#>)\n"
  239.                "MOVE <zone#> <address> <mail type> (move mail from <zone#> to another)\n"
  240.                "CHANGE <address> <mail type> (change all mail to <address> to <mail type>)\n"
  241.  
  242. /*
  243.             Commented this out; too much damn trouble.
  244.             Code (doesn't work) is still there.
  245. */
  246.  
  247.  
  248. /*
  249.                " (alternate: CHANGE ALL [<ZONE> <#>] <type> (change all mail to <type>)\n"
  250. */
  251.  
  252.                "POLL <address> [<password>] (force a call to <address> by creating *.CLO)\n"
  253.                "SPAWN <string> (spawn <string>...use COMMAND.COM /c for batch files)\n"
  254.                "IFERRORLEVEL <!<>=> <#> <command> (process <command> if last ERRORLEVEL\n"
  255.                "                                   from SPAWN command satisfies compare)\n"
  256.                "<zone#>:<net#>/<node#> <mail type: Crash, Hold, etc.> <archive command>\n"
  257.                " [Any Key]");
  258.                getch();
  259.                fprintf(stderr,"\b\b\b\b\b\b\b\b\b\b"
  260.                "END (means stop now and do pass through your zone)\n"
  261.                "BREAK (means don't do pass through your zone--stop NOW)\n"
  262.                "GOTO <schedtag> (jump to schedule tag <schedtag>)\n"
  263.                "IFINTIME <hh:mm:ss> <hh:mm:ss> <command> (process <command> if in timeframe)\n"
  264.                "IFDOW <#> <command> (process <command> if <#>=day of week (1-7 from Sunday))\n"
  265.                "IFDOM <#> <command> (process <command> if <#>=day of month (1-31))\n"
  266.                "IFMON <#> <command> (process <command> if <#>=month (1-12))\n"
  267.                "DEBUG (means get verbose, show *everything*)\n"
  268.                "MORE (means more info, but don't get totally ridiculous)\n");
  269.                exit(0);
  270.   }
  271.  
  272.   /* Use command line arguments if available */
  273.  
  274.   if (argc>1) strcpy(configfile,argv[1]);
  275.   if(argc>2) strcpy(schedtag,argv[2]);
  276.   if(argc>3 && *argv[3]=='!') debug=1;
  277.   if(argc>3 && *argv[3]=='?') more=1;
  278.  
  279.   /* Try to find our environment variables (overrides command line) */
  280.  
  281.   p=getenv("MAKECFG");
  282.   if(*p && p) strcpy(configfile,getenv("MAKECFG"));
  283.   p=getenv("MAKESCHD");
  284.   if(*p && p) strcpy(schedtag,getenv("MAKESCHD"));
  285.  
  286.   if(findfirst(configfile,&f,0)) {
  287.  
  288.     /* Couldn't find configfile; look for BINKLEY environment variable
  289.        and then BINKLEY.CFG */
  290.  
  291.     if(getenv("BINKLEY")) {
  292.         strcpy(configfile,getenv("BINKLEY"));
  293.         if(configfile[strlen(configfile)-1]=='\\')
  294.             configfile[strlen(configfile)-1]=0;
  295.         strcat(configfile,"\\BINKLEY.CFG");
  296.     }
  297.     else strcpy(configfile,"BINKLEY.CFG");
  298.   }
  299.  
  300.   if(stristr(configfile,"BINKLEY.CFG"))
  301.     usingbink=1;              /* Look for APPLICATIONs */
  302.  
  303.   fp=analyze(configfile);    /* Open file, find schedule tag, etc. */
  304.  
  305.   ctrlbrk(break_handler);    /* Handles CTRL-BREAK */
  306.   harderr(hardware_error);    /* Aborts on hardware error INT 0x24 */
  307.  
  308.   atexit(deinit);            /* Removes marker file */
  309.  
  310.   fclose(fopen("MAKEARC.RUN","w"));    /* Marker file; "I'm running!" */
  311.  
  312.   while(!feof(fp)) {                    /* Process config file--main loop */
  313.     lastpos=ftell(fp);
  314.     strcpy(outbound,root);                /* Reset outbound variable */
  315.     doingnet=doingzone=doingdomain=0;    /* Reset special condition flags */
  316.     if(!hiszone) hiszone=myzone;
  317.     if(!fgets(s,133,fp)) goto DoneWithFile;
  318.     lines++;                            /* Line counter for error msgs */
  319.     if(debug) printf("%u. %s",lines,s);    /* Display line if debug on */
  320.     if(p=(strchr(s,';'))) *p=0;            /* Lose trailing comments */
  321.     stripcr(s);                            /* Lose cr/lf */
  322.     lstrip(s);                            /* Lose leading spaces */
  323.     rstrip(s);                            /* Lose trailing spaces */
  324.     if(!*s || *s==';') continue;        /* Skip blank or comment lines */
  325.     while(p=(strchr(s,'\t'))) *p=' ';    /* Get rid of tabs */
  326.     lstrip(s);                            /* Strip extraneous spaces */
  327.     rstrip(s);
  328.     p=s;
  329.  
  330. /* This label used to merge back into the stream after IFERRORLEVEL */
  331.  
  332. AfterERRORLEVEL:
  333.  
  334.     if(!strnicmp(p,"OUTBOUND ",9) || !strnicmp(p,"HOLD ",5)) {
  335.         if(toupper(*p)=='O')p+=9;        /* Main outbound directory */
  336.         else p+=5;
  337.         lstrip(p);
  338.         while(pp=(strchr(p,'/'))) *pp='\\';   /* Convert slashes to backslashes */
  339.         strncpy(outbound,p,80);
  340.         outbound[79]=0;
  341.         if(outbound[strlen(outbound)-1]=='\\') outbound[strlen(outbound)-1]=0;
  342.         strcpy(root,outbound);
  343.         p=strrchr(root,'\\');
  344.         if(p) {
  345.             p++;
  346.             printf("Current Domain: `%s'\n",p);
  347.         }
  348.         if(debug || more) printf("Outbound dir=`%s'\n",root);
  349.         continue;
  350.     }
  351.  
  352.     else if(!strnicmp(p,"NETDIR ",7) || !strnicmp(p,"NETMAIL ",8)) {
  353.         if(toupper(p[7])=='L') p+=8;    /* Net directory (w/ MSG) */
  354.         else p+=7;
  355.         lstrip(p);
  356.         while(pp=(strchr(p,'/'))) *pp='\\';   /* Convert slashes to backslashes */
  357.         strncpy(netdir,p,80);
  358.         netdir[79]=0;
  359.         if(netdir[strlen(netdir)-1]=='\\') netdir[strlen(netdir)-1]=0;
  360.         if(debug || more)printf("Net dir=`%s'\n",netdir);
  361.         continue;
  362.     }
  363.  
  364.     else if(!strnicmp(p,"ADDRESS ",8)) {    /* Our address */
  365.         p+=8;
  366.         lstrip(p);
  367.         p=strtok(p,":");
  368.         if(!p) {
  369.             fprintf(stderr,"\nMissing Zone\n");
  370.             say_error(lastpos,fp);
  371.             continue;
  372.         }
  373.         myzone=(unsigned int)atol(p);
  374.         if(!myzone) {
  375.             fprintf(stderr,"\nZero Zone\n");
  376.             say_error(lastpos,fp);
  377.             continue;
  378.         }
  379.         p=strtok(0,"/");
  380.         if(!p) {
  381.             fprintf(stderr,"\nMissing Net\n");
  382.             say_error(lastpos,fp);
  383.             continue;
  384.         }
  385.         mynet=(unsigned int)atol(p);
  386.         if(!mynet) {
  387.             fprintf(stderr,"\nZero Net\n");
  388.             say_error(lastpos,fp);
  389.             continue;
  390.         }
  391.         p=strtok(0,".@ ");
  392.         if(!p) {
  393.             fprintf(stderr,"\nMissing Node\n");
  394.             say_error(lastpos,fp);
  395.             continue;
  396.         }
  397.         mynode=(unsigned int)atol(p);
  398.         p=strtok(0,"@ ");
  399.         if(!p) mypoint=0;
  400.         else mypoint=(unsigned int)atol(p);
  401.         if(debug || more) {
  402.             if(mypoint)printf("Address=`%u:%u/%01u.%01u'\n",myzone,mynet,mynode,mypoint);
  403.             else printf("Address=`%u:%u/%01u'\n",myzone,mynet,mynode);
  404.         }
  405.         continue;
  406.     }
  407.  
  408.     else if(usingbink) {            /* Check for Binkley.cfg APPLICATIONs */
  409.         if(strnicmp(p,"APPLICATION MAKEARC ",20)) continue; /* Not ours */
  410.         p+=20;
  411.         lstrip(p);
  412.     }
  413.  
  414.     else if(!stricmp(p,"MORE")) {    /* Toggle more */
  415.         more=1-more;
  416.         if(debug) printf("More ON\n");
  417.         else printf("More OFF\n");
  418.         continue;
  419.     }
  420.  
  421.     else if(!stricmp(p,"DEBUG")) {    /* Toggle debug */
  422.         debug=1-debug;
  423.         if(debug) printf("Debug ON\n");
  424.         else printf("Debug OFF\n");
  425.         continue;
  426.     }
  427.  
  428.     else if(!strnicmp(p,"POLL ",5)) {    /* Create empty poll *.CLO file */
  429.         p+=5;
  430.         make_poll(p,lastpos,fp);
  431.         continue;
  432.     }
  433.  
  434.     else if(!strnicmp(p,"SCHED ",6)) continue;    /* Skip schedule tags */
  435.  
  436.     else if(!strnicmp(p,"ARCCMD ",7)) {    /* Default archiver command */
  437.         p+=7;
  438.         lstrip(p);
  439.         strncpy(arccmd,p,80);
  440.         arccmd[79]=0;
  441.         strcpy(tempcmd,arccmd);
  442.         if(debug || more)printf("Archiver command=`%s <arcname> <pktname>'\n",arccmd);
  443.         continue;
  444.     }
  445.  
  446.     else if(!stricmp(p,"MSG")) {    /* Make MSG attaches instead of FLO */
  447.         msgattach=1;
  448.         if(debug || more)printf("Making *.MSG attaches\n");
  449.         continue;
  450.     }
  451.  
  452.     else if(!stricmp(p,"FLO")) {    /* Opposite of MSG */
  453.         msgattach=0;
  454.         if(debug || more)printf("Making *.?LO attaches\n");
  455.         continue;
  456.     }
  457.  
  458.     else if(!strnicmp(p,"ALLTYPE ",8)) {    /* Default mail type */
  459.         p+=8;
  460.         lstrip(p);
  461.         alltype=toupper(*p);
  462.         if(debug || more)printf("Default mail type=`%c'\n",alltype);
  463.         continue;
  464.     }
  465.  
  466.     else if(!strnicmp(p,"SPAWN ",6)) {        /* Do external command */
  467.         p+=6;
  468.         lstrip(p);
  469.         printf("SPAWNing `%s'\n",p);
  470.         lastlevel=spawnit(p);
  471.         continue;
  472.     }
  473.  
  474.     else if(!strnicmp(p,"IFERRORLEVEL ",13)) {    /* Respond to ERRORLEVEL */
  475.  
  476.         char oper;
  477.         char level;
  478.  
  479.         p+=13;
  480.         lstrip(p);
  481.         oper=*p;
  482.         p++;
  483.         lstrip(p);
  484.         level=(char)atoi(p);
  485.         p=skip_nonwhite(p);
  486.         lstrip(p);
  487.         if(oper=='!' && lastlevel!=level) {
  488.             printf("ERRORLEVEL match...\n");
  489.             goto AfterERRORLEVEL;
  490.         }
  491.         else if(oper=='>' && lastlevel>level) {
  492.             printf("ERRORLEVEL match...\n");
  493.             goto AfterERRORLEVEL;
  494.         }
  495.         else if(oper=='<' && lastlevel<level) {
  496.             printf("ERRORLEVEL match...\n");
  497.             goto AfterERRORLEVEL;
  498.         }
  499.         else if(lastlevel==level) {
  500.             printf("ERRORLEVEL match...\n");
  501.             goto AfterERRORLEVEL;
  502.         }
  503.         if(debug || more) printf("ERRORLEVEL didn't match...\n");
  504.         continue;
  505.     }
  506.  
  507.     else if(!strnicmp(p,"IFINTIME ",9)) {
  508.  
  509.         long tt1,tt2,tt3;
  510.         struct tm *tt;
  511.  
  512.         p+=9;
  513.         lstrip(p);
  514.         tt1=(atol(p) * 3600L);
  515.         p=to_delim(p,":");
  516.         if(*p==':')p++;
  517.         tt1+=(atol(p) * 60L);
  518.         p=to_delim(p,":");
  519.         if(*p==':')p++;
  520.         tt1+=atol(p);
  521.         p=skip_nonwhite(p);
  522.         lstrip(p);
  523.         tt2=(atol(p) * 3600L);
  524.         p=to_delim(p,":");
  525.         if(*p==':')p++;
  526.         tt2+=(atol(p) * 60L);
  527.         p=to_delim(p,":");
  528.         if(*p==':')p++;
  529.         tt2+=atol(p);
  530.         p=skip_nonwhite(p);
  531.         lstrip(p);
  532.         tt3=time(NULL);
  533.         tt=localtime(&tt3);
  534.         tt3=(long)tt->tm_hour * 3600L;
  535.         tt3+=(long)tt->tm_min * 60L;
  536.         tt3+=(long)tt->tm_sec;
  537.         if (tt3<tt1 || tt3>tt2) continue;    /* Not in timeframe */
  538.         goto AfterERRORLEVEL;
  539.     }
  540.  
  541.     else if(!strnicmp(p,"IFDOW ",6)) {    /* If day of week (1-7) from Sun */
  542.  
  543.         struct tm *tt;
  544.         long tl;
  545.         int dow;
  546.  
  547.         p+=6;
  548.         lstrip(p);
  549.         dow=atoi(p);
  550.         p=skip_nonwhite(p);
  551.         lstrip(p);
  552.         tl=time(NULL);
  553.         tt=localtime(&tl);
  554.         if(tt->tm_wday+1 != dow) continue;    /* Not right day of week */
  555.         goto AfterERRORLEVEL;
  556.     }
  557.  
  558.     else if(!strnicmp(p,"IFMONTH ",8)) {    /* If month (1-12) */
  559.  
  560.         struct tm *tt;
  561.         long tl;
  562.         int mon;
  563.  
  564.         p+=8;
  565.         lstrip(p);
  566.         mon=atoi(p);
  567.         p=skip_nonwhite(p);
  568.         lstrip(p);
  569.         tl=time(NULL);
  570.         tt=localtime(&tl);
  571.         if(tt->tm_mon+1 != mon) continue;    /* Not right month */
  572.         goto AfterERRORLEVEL;
  573.     }
  574.  
  575.     else if(!strnicmp(p,"IFDOM ",6)) {    /* If day of month (1-31) */
  576.  
  577.         struct tm *tt;
  578.         long tl;
  579.         int dom;
  580.  
  581.         p+=6;
  582.         lstrip(p);
  583.         dom=atoi(p);
  584.         p=skip_nonwhite(p);
  585.         lstrip(p);
  586.         tl=time(NULL);
  587.         tt=localtime(&tl);
  588.         if(tt->tm_mday != dom) continue;    /* Not right day of month */
  589.         goto AfterERRORLEVEL;
  590.     }
  591.  
  592. /* Have pity on TC; break up the if...else if chain */
  593.  
  594.     if(!stricmp(p,"BREAK")) {                /* No global pass through our zone */
  595.         if(debug || more) printf("BREAK encountered.\n");
  596.         break;
  597.     }
  598.  
  599.     else if(!stricmp(p,"END")) {            /* Global then end */
  600.         if(debug || more) printf("END encountered.\n");
  601.         goto DoneWithFile;
  602.     }
  603.  
  604.     else if(!strnicmp(p,"GOTO ",5)) {        /* Jump to a schedule tag */
  605.         p+=5;
  606.         lstrip(p);
  607.         printf("Branching to SCHED tag `%s'\n",p);
  608.         if(!find_sched(fp,p,1)) exit(10);
  609.         continue;
  610.     }
  611.  
  612.     else if(!strnicmp(p,"ROUTE ",6)) {  /* Misdirect mail :-) */
  613.         p+=6;
  614.         p=strtok(p,":");
  615.         if(!p) {
  616.             fprintf(stderr,"\nMissing Zone\n");
  617.             say_error(lastpos,fp);
  618.             continue;
  619.         }
  620.         p=skip_white(p);
  621.         rzone=(unsigned int)atol(p);
  622.         p=strtok(0,"/");
  623.         if(!p) {
  624.             fprintf(stderr,"\nMissing Net\n");
  625.             say_error(lastpos,fp);
  626.             continue;
  627.         }
  628.         rnet=(unsigned int)atol(p);
  629.         p=strtok(0,".;\n");
  630.         if(!p) {
  631.             fprintf(stderr,"\nMissing Node\n");
  632.             say_error(lastpos,fp);
  633.             continue;
  634.         }
  635.         rnode=(unsigned int)atol(p);
  636.         p=strtok(0,";\n");
  637.         if(!p) rpoint=0;
  638.         else rpoint=(unsigned int)atol(p);
  639.         if(rzone && !rnet) rzone=0;
  640.         if(debug || more) {
  641.             if(!rpoint)printf("Route To=`%u:%u/%01u.%01u'\n",rzone,rnet,rnode,rpoint);
  642.             else printf("Route To=`%u:%u/%01u'\n",rzone,rnet,rnode);
  643.         }
  644.         continue;
  645.     }
  646.  
  647.     else if(!strnicmp(p,"MOVE ",5)) {    /* Move mail from outbound->outbound */
  648.         p+=5;
  649.         lstrip(p);
  650.         move_prep(p,lastpos,fp);
  651.         continue;
  652.     }
  653.  
  654.     else if(!strnicmp(p,"CHANGE ",6)) {    /* Change mail's type */
  655.         p+=6;
  656.         lstrip(p);
  657.         change_mail(p,lastpos,fp);
  658.         continue;
  659.     }
  660.  
  661.     else if(!strnicmp(p,"DOMAIN",6)) {     /* Make pass through a domain */
  662.  
  663.         char *ppp;
  664.  
  665.         p+=6;
  666.         lstrip(p);
  667.         if(*p) {
  668.             ppp=skip_nonwhite(p);
  669.             if(*ppp) {
  670.                 *ppp=0;
  671.                 ppp++;
  672.                 ppp=skip_white(ppp);
  673.             }
  674.             while(pp=(strchr(p,'/')))
  675.                 *pp='\\';   /* Convert slashes to backslashes */
  676.             strncpy(outbound,p,80);
  677.             outbound[79]=0;
  678.             if(outbound[strlen(outbound)-1]=='\\')
  679.                 outbound[strlen(outbound)-1]=0;
  680.             strcpy(root,outbound);
  681.             if(debug || more) printf("Outbound dir=`%s'\n",root);
  682.             if(*ppp) {
  683.                 type=toupper(*ppp);
  684.                 ppp=skip_nonwhite(ppp);
  685.                 ppp=skip_white(ppp);
  686.                 if(*ppp) {
  687.                     strcpy(arccmd,ppp);
  688.                 }
  689.                 else strcpy(arccmd,tempcmd);
  690.             }
  691.             else {
  692.                 type=alltype;
  693.                 strcpy(arccmd,tempcmd);
  694.             }
  695.         }
  696.         else {
  697.             type=alltype;
  698.             strcpy(arccmd,tempcmd);
  699.         }
  700.         p=strrchr(root,'\\');
  701.         if(p)p++;
  702.         else p="Current";
  703.         printf("Domain `%s'",p);
  704.         if(rzone) printf(" -=> %u:%u.%u",rzone,rnet,rnode);
  705.         printf("\n");
  706.         doingdomain=1;
  707.     }
  708.  
  709.     else {
  710.         if(!strnicmp(p,"NET ",4)) {    /* Make a pass through a whole net */
  711.             doingnet=1;
  712.             p+=4;
  713.             lstrip(p);
  714.         }
  715.  
  716.         else if(!strnicmp(p,"ZONE ",5)) {    /* Do a global pass through a zone */
  717.             p+=5;
  718.             lstrip(p);
  719.             doingzone=1;
  720.         }
  721.  
  722.         /* Otherwise it's a full address to send to */
  723.  
  724.         p=strtok(p,":");
  725.         if(!p) {
  726.             fprintf(stderr,"\nMissing Zone\n");
  727.             say_error(lastpos,fp);
  728.             continue;
  729.         }
  730.         hiszone=(unsigned int)atol(p);
  731.         if(!hiszone) {
  732.             fprintf(stderr,"\nZero Zone\n");
  733.             say_error(lastpos,fp);
  734.             continue;
  735.         }
  736.         if(!doingzone) {
  737.             p=strtok(0,"/");
  738.             if(!p) {
  739.                 fprintf(stderr,"\nMissing Net\n");
  740.                 say_error(lastpos,fp);
  741.                 continue;
  742.             }
  743.             hisnet=(unsigned int)atol(p);
  744.             if(!hisnet) {
  745.                 fprintf(stderr,"\nZero Net\n");
  746.                 say_error(lastpos,fp);
  747.                 continue;
  748.             }
  749.             if(!doingnet) {
  750.                 p=strtok(0," ;");
  751.                 if(!p) {
  752.                     fprintf(stderr,"\nMissing Node\n");
  753.                     say_error(lastpos,fp);
  754.                     continue;
  755.                 }
  756.                 hisnode=(unsigned int)atol(p);
  757.                 if(strchr(p,'.')) {
  758.                     p=strchr(p,'.');
  759.                     p++;
  760.                     hispoint=(unsigned int)atol(p);
  761.                 }
  762.                 else hispoint=0;
  763.             }
  764.             else {
  765.                 hisnode=0;
  766.                 hispoint=0;
  767.             }
  768.         }
  769.         else {
  770.             hisnet=0;
  771.             hisnode=0;
  772.             hispoint=0;
  773.         }
  774.         p=strtok(0," ;");
  775.         if(p) {
  776.             type=toupper(*p);
  777.         }
  778.         else type=alltype;
  779.         p=strtok(0,";\n");
  780.         if(p) {
  781.             lstrip(p);
  782.             rstrip(p);
  783.             strcpy(arccmd,p);
  784.         }
  785.         else strcpy(arccmd,tempcmd);
  786.  
  787.         if(!doingnet && !doingzone) {
  788.             sprintf(s,"%s\\%04x%04x.?UT",outbound,hisnet,hisnode); /* Find just this one guy for now */
  789.             if(!hispoint)printf("%u:%u/%01u",hiszone,hisnet,hisnode); /* Tell console */
  790.             else printf("%u:%u/%01u.%01u",hiszone,hisnet,hisnode,hispoint);
  791.         }
  792.         else if(doingnet) {
  793.             sprintf(s,"%s\\%04x*.?UT",outbound,hisnet); /* Find anyone in net */
  794.             printf("Net %u:%u",hiszone,hisnet);
  795.         }
  796.         else {
  797.             sprintf(outbound,"%s.%03x",root,hiszone);
  798.             sprintf(s,"%s\\*.?UT",outbound);
  799.             printf("Zone %u (%s)",hiszone,outbound);
  800.         }
  801.         if(rzone) printf(" -=> %u:%u/%u",rzone,rnet,rnode);
  802.         printf("\n");
  803.     }
  804.  
  805. /* The following label is used to goto for the default pass through
  806.    the default zone (unless BREAK is encountered) at termination. */
  807.  
  808. OneMoreTime:
  809.  
  810.     if(doingdomain) sprintf(s2,"%s.*",root); /* Special find-the-outbound */
  811.     else strcpy(s2,outbound);                /* code. */
  812.     do {
  813.         founddir=findfirst(s2,&d,FA_DIREC);
  814.     } while(!founddir && !(d.ff_attrib & FA_DIREC));
  815.  
  816.     if(founddir && !doingdomain) {    /* No outbound directory?  Uh oh... */
  817.         fprintf(stderr,"\nOutbound directory %s doesn't seem to exist.\n",s2);
  818.     }
  819.  
  820.     while(!founddir) {    /* Loop once for anything but DOMAIN */
  821.         p=strrchr(d.ff_name,'.');
  822.         if(p) sprintf(outbound,"%s%s",root,p);
  823.         else strcpy(outbound,root);
  824.  
  825.         if(doingdomain) {    /* Get zone # from outbound extension */
  826.             hiszone=0;
  827.             sprintf(s,"%s\\*.?UT",outbound); /* Setup to find any pkt in zone */
  828.             p=strrchr(outbound,'.');
  829.             if(p) {
  830.                 p++;
  831.                 strncpy(temp,p,3);
  832.                 hiszone=(word)strtol(temp,&p,16);
  833.             }
  834.             if(!hiszone)hiszone=myzone;
  835.             printf(" Zone %u",hiszone);  /* and display it */
  836.             if(rzone) printf(" -=> %u:%u/%u",rzone,rnet,rnode);
  837.             printf("\n");
  838.             if(debug || more) printf(" Outbound: `%s'\n",outbound);
  839.         }
  840.  
  841.         while(!findfirst(s,&f,0)) {    /* Never leave one after processing */
  842.             if(didbreak) {            /* CTRL-BREAK pressed; outta here */
  843.                 if(fp)fclose(fp);
  844.                 fprintf(stderr,"\nExitting in response to user break.\x1b[0m\n");
  845.                 exit(99);
  846.             }
  847.             if(hiszone!=myzone) sprintf(outbound,"%s.%03x",root,hiszone);
  848.             strcpy(pktfile,f.ff_name);
  849.             strcpy(origpkt,strupr(pktfile));
  850.             strncpy(temp,pktfile,4);
  851.             temp[4]=0;
  852.             hisnet=(word)strtol(temp,&p,16);
  853.             strncpy(temp,&pktfile[4],4);
  854.             temp[4]=0;
  855.             hisnode=(word)strtol(temp,&p,16);
  856.             sprintf(pktfile,"%s\\%s",outbound,f.ff_name);
  857.             if(rzone) {
  858.                 strcpy(arcfile,arcname(rnet,rnode));
  859.             }
  860.             else {
  861.                 strcpy(arcfile,arcname(hisnet,hisnode));
  862.             }
  863.             strcat(arcfile,".*");
  864.             t=time(NULL);
  865.             ltoa(t,temp,36);
  866.             sprintf(s2,"%s\\%6.6s%02hx.PKT",outbound,temp,(char)t_counter++);
  867.             rename(pktfile,s2);
  868.             strcpy(pktfile,s2);
  869.             if(rzone && rzone!=myzone) {
  870.                 sprintf(outbound,"%s.%03x",root,rzone);
  871.             }
  872.             sprintf(s2,"%s\\%s",outbound,arcfile);
  873.             if(findfirst(s2,&f,0)) {
  874.                 if(rzone) {
  875.                     sprintf(arcfile,"%s\\%s.MO1",outbound,arcname(rnet,rnode));
  876.                 }
  877.                 else {
  878.                     sprintf(arcfile,"%s\\%s.MO1",outbound,arcname(hisnet,hisnode));
  879.                 }
  880.                 new=1;
  881.             }
  882.             else {
  883.                 sprintf(arcfile,"%s\\%s",outbound,f.ff_name);
  884.                 new=0;
  885.                 if(f.ff_fsize==0L) {    /* Just a marker file */
  886.                     new=1;
  887.                     unlink(arcfile);
  888.                     p=strrchr(arcfile,'.');
  889.                     if(!p) {        /* Invalid filename */
  890.                         strcat(arcfile,".MO1");
  891.                     }
  892.                     else {
  893.                         arcfile[strlen(arcfile)-1]++;
  894.                         if(!isdigit(arcfile[strlen(arcfile)-1])) {
  895.                             next_name(p);    /* Inc filename */
  896.                         }
  897.                     }
  898.                 }
  899.             }
  900.             if(new)printf("Making ");
  901.             else printf("Adding to ");
  902.             if(hispoint)printf("archive %s for %u:%u/%01u.%01u...\n",arcfile,hiszone,hisnet,hisnode,hispoint);
  903.             else printf("archive %s for %u:%u/%01u...\n",arcfile,hiszone,hisnet,hisnode);
  904.             if(rzone) {
  905.                 if(rpoint)printf("Routing it to %u:%u/%01u\n",rzone,rnet,rnode,rpoint);
  906.                 else printf("Routing it to %u:%u/%01u\n",rzone,rnet,rnode);
  907.             }
  908.             rc=makearc(arcfile,pktfile,origpkt,outbound);
  909.             if(!rc) { /* Archiver error */
  910.     MakeFloAnyway:
  911.               if(new) {
  912.                 p=strrchr(origpkt,'.');
  913.                 if(!p)p=".F";
  914.                 strcpy(s2,&p[1]);
  915.                 if(toupper(*s2)=='O') *s2='F';
  916.                 if(type) *s2=type;
  917.                 else if (alltype) *s2=alltype;
  918.                 if(msgattach) {
  919.                     if(rzone) makemessage(rzone,rnet,rnode,rpoint,arcfile,*s2);
  920.                     else makemessage(hiszone,hisnet,hisnode,hispoint,arcfile,*s2);
  921.                 }
  922.                 else {
  923.                     if(rzone) makeflo(rzone,rnet,rnode,rpoint,arcfile,*s2);
  924.                     else makeflo(hiszone,hisnet,hisnode,hispoint,arcfile,*s2);
  925.                 }
  926.               }
  927.               else if(!msgattach) {   /* Quick&dirty check for orphaned archives (Flow files only) */
  928.                   if(rzone) new=check_4flo(rzone,rnet,rnode,rpoint);
  929.                   else new=check_4flo(hiszone,hisnet,hisnode,hispoint);
  930.                   if(new) goto MakeFloAnyway;
  931.               }
  932.             }
  933.             else if(rc<0) {
  934.                 fprintf(stderr,"Rename failed!\n");
  935.                 break;    /* Rename error; avoid fatal embrace */
  936.             }
  937.         }
  938.         do {    /* Loop through all outbound dirs if DOMAIN */
  939.             founddir=findnext(&d);
  940.         } while(!founddir && !(d.ff_attrib & FA_DIREC));
  941.     }
  942.     if(!fp) break;
  943.     if(feof(fp)) {        /* End of file...implicit END */
  944. DoneWithFile:            /* Terminate on END or big error */
  945.         fclose(fp);
  946.         fp=NULL;
  947.         sprintf(s,"%s\\*.?UT",outbound);    /* Find everybody left */
  948.         strcpy(arccmd,tempcmd);
  949.         type=alltype;
  950.         hiszone=myzone;
  951.         doingnet=doingzone=doingdomain=0;
  952.         printf("Default pass through default zone (%s)...\n",root);
  953.         strcpy(outbound,root);
  954.         goto OneMoreTime;
  955.     }
  956.   }
  957.   if(fp) fclose(fp);
  958.  
  959.   /* Display time of run */
  960.  
  961.   lastpos=(time(NULL)-starttime)/60L;
  962.   printf("Run time: %ld minutes %ld seconds\n",lastpos,(time(NULL)-starttime)-(lastpos*60L));
  963. }
  964.  
  965.  
  966.  
  967. void cdecl deinit (void) {
  968.  
  969.     unlink("MAKEARC.RUN");    /* Get rid of marker file */
  970. }
  971.  
  972.  
  973.  
  974. void pascal say_error (long lastpos,FILE *fp) {
  975.  
  976.     char s[256];
  977.  
  978.     /* Give some info on obvious error encountered in config file */
  979.  
  980.     fseek(fp,lastpos,SEEK_SET);
  981.     if(!fgets(s,256,fp)) return;
  982.     stripcr(s);
  983.     fprintf(stderr,"ERROR line #%u:  `%s'\n\n",lines,s);
  984. }
  985.  
  986.  
  987.  
  988. int cdecl break_handler (void) {
  989.  
  990.     /* Display message and set ctrl-break flag */
  991.  
  992.     fprintf(stderr,"\n\x1b[0;1;31mAs soon as it's safe.\n");
  993.     didbreak=1;
  994.     return 0;
  995. }
  996.  
  997.  
  998. char * pascal arcname (word net,word node) {
  999.  
  1000.     /* Return outbound-style archive (bundle) filename */
  1001.  
  1002.     static char name[9];
  1003.  
  1004.     sprintf(name,"%04x%04x",mynet-net,mynode-node);
  1005.     return name;
  1006. }
  1007.  
  1008.  
  1009. char * pascal filename (word net,word node) {
  1010.  
  1011.     /* Return outbound-style filename */
  1012.  
  1013.     static char name[9];
  1014.  
  1015.     sprintf(name,"%04x%04x",net,node);
  1016.     return name;
  1017. }
  1018.  
  1019.  
  1020. void pascal next_name (char *p) {
  1021.  
  1022.     /* Increment archive name extension */
  1023.  
  1024.     strupr(p);
  1025.     if(!strncmp(p,".MO",3)) strcpy(p,".TU1");
  1026.     else if(!strncmp(p,".TU",3)) strcpy(p,".WE1");
  1027.     else if(!strncmp(p,".WE",3)) strcpy(p,".TH1");
  1028.     else if(!strncmp(p,".TH",3)) strcpy(p,".FR1");
  1029.     else if(!strncmp(p,".FR",3)) strcpy(p,".SA1");
  1030.     else if(!strncmp(p,".SA",3)) strcpy(p,".SU1");
  1031.     else strcpy(p,".MO1");
  1032. }
  1033.  
  1034.  
  1035.  
  1036. char * pascal fidodate (void) {  /* THIS IS THE RIGHT WAY, DAMMIT!!! */
  1037.  
  1038.  char months[12][4]={
  1039.     "Jan",
  1040.     "Feb",
  1041.     "Mar",
  1042.     "Apr",
  1043.     "May",
  1044.     "Jun",
  1045.     "Jul",
  1046.     "Aug",
  1047.     "Sep",
  1048.     "Oct",
  1049.     "Nov",
  1050.     "Dec"
  1051.  };
  1052.  static char fdate[20];
  1053.  struct date dos_date;
  1054.  struct time dos_time;
  1055.  
  1056. /* Sample output:  '26 Jul 89  06:23:47' */
  1057.  
  1058.  getdate(&dos_date);    /* TC structs; use what you got */
  1059.  gettime(&dos_time);
  1060.  
  1061.  sprintf(fdate,"%02hu %s %02d  %02hu:%02hu:%02hu",dos_date.da_day,months[dos_date.da_mon-1],dos_date.da_year%100,dos_time.ti_hour,dos_time.ti_min,dos_time.ti_sec);
  1062.  return(fdate);            /*   ^^--NOTE!!! DAMMIT!! */
  1063. }
  1064.  
  1065.  
  1066.  
  1067. FILE * pascal analyze (char *file) {
  1068.  
  1069.     int handle;
  1070.     static FILE *pf;
  1071.  
  1072.     /* Opens config file, finds starting sched if any, returns handle */
  1073.  
  1074.     handle=_open(file,O_RDONLY | O_TEXT | O_DENYWRITE);
  1075.     if(handle==-1) goto OpenError;
  1076.  
  1077.     pf=fdopen(handle,"rt");
  1078.     if(pf==NULL) {
  1079. OpenError:
  1080.         fprintf(stderr,"\nCan't open control file \'%s\'\n",file);
  1081.         exit(5);
  1082.     }
  1083.     setmode(handle,O_TEXT);        /* DAMMIT ANYWAY!!! */
  1084.     printf("\nReading control file \'%s\'...\n",file);
  1085.  
  1086.     if(*schedtag) {
  1087.         if(find_sched(pf,schedtag,0)) {
  1088.             printf("Processing schedule tag '%s'\n",schedtag);
  1089.             *schedtag=0;
  1090.         }
  1091.         else exit(10);
  1092.     }
  1093.     return (pf);
  1094. }
  1095.  
  1096.  
  1097. word pascal makeflo (word zone,word net,word node,word point,char *sendfile,char type) {
  1098.  
  1099.     int handle;
  1100.     char s[133];
  1101.     char tries=0;
  1102.     int x;
  1103.  
  1104.     /* Create a .?LO file */
  1105.  
  1106.     if(type=='N' || type=='O') type='F';
  1107.     sprintf(s,"%s\\%04x%04x.%cLO",outbound,net,node,type);
  1108.     printf("Creating/appending flow attach `%s'...\n",s);
  1109. ReTry:
  1110.     handle=_open(s,O_RDWR | O_BINARY | O_APPEND | O_DENYWRITE);
  1111.     if(handle==-1) handle=creat(s,S_IWRITE);
  1112.     if(handle==-1) {
  1113.         if(tries++ < 9) {
  1114.             if(debug) printf("Can't access %s; retry #%hu\n",s,tries);
  1115.             goto ReTry;
  1116.         }
  1117.         fprintf(stderr,"\nCouldn't open `%s' (errno=%d)\n",s,errno);
  1118.         return 1;
  1119.     }
  1120.     lseek(handle,0L,SEEK_END);
  1121.     sprintf(s,"#%s\r\n",sendfile);
  1122.     x=strlen(s);
  1123.     if(_write(handle,(void *)s,(unsigned int)x)<x) {
  1124.         _close(handle);
  1125.         fprintf(stderr,"\nProblem writing to flow file...\n");
  1126.         return 1;
  1127.     }
  1128.     _close(handle);
  1129.     return 0;
  1130. }
  1131.  
  1132.  
  1133.  
  1134. char pascal check_4flo (word zone,word net,word node,word point) {
  1135.  
  1136.     char s[133];
  1137.     struct ffblk f;
  1138.  
  1139.     /* Quick and crude check for orphaned bundles */
  1140.  
  1141.     sprintf(s,"%s\\%04x%04x.?LO",outbound,net,node);
  1142.     if(findfirst(s,&f,0)) {
  1143. Orphan:
  1144.         if(debug || more) printf("Apparently orphaned bundle...\n");
  1145.         return 1;
  1146.     }
  1147.     if(f.ff_fsize==0L) goto Orphan;
  1148.     return 0;
  1149. }
  1150.  
  1151.  
  1152.  
  1153. word pascal makemessage (word zone,word net,word node,word point,char *sendfile,char type) {
  1154.  
  1155.     int handle;
  1156.     struct ffblk f;
  1157.     static word x=1;
  1158.     char s[133];
  1159.     register word y;
  1160.     struct _msg msg;
  1161.     char tries=0;
  1162.  
  1163.     /* Make *.MSG attach */
  1164.  
  1165.     msg.attr = MSGLOCAL | MSGKILL | MSGFILE;
  1166.     strncpy(msg.subj,sendfile,72);
  1167.     msg.subj[71]=0;
  1168.     msg.dest=node;
  1169.     msg.dest_net=net;
  1170.     msg.orig=mynode;
  1171.     msg.orig_net=mynet;
  1172.     strcpy(msg.date,fidodate());
  1173.     strcpy(msg.from,"Attach Message");
  1174.     strcpy(msg.to,"Mail Processor");
  1175.     for(y=0;y<4;y++) msg.msg_filler[y]=0;
  1176.     msg.reply=0;
  1177.     msg.up=0;
  1178.     msg.times=0;
  1179.     msg.cost=0;
  1180.     sprintf(s,"%s\\%u.MSG",netdir,x);
  1181.     fprintf(stderr,"Creating damn file attach msg `%s'...\n",s);
  1182. ReTry:
  1183.     while(!findfirst(s,&f,0)) {
  1184.         x++;
  1185.         if(!x) {
  1186.             fprintf(stderr,"\nDamn Msg directory is full\n");
  1187.             exit(1);
  1188.         }
  1189.         sprintf(s,"%s\\%u.MSG",netdir,x);
  1190.     }
  1191.     handle=creat(s,S_IWRITE);
  1192.     if(handle==-1) {
  1193.         if(tries++<9) {
  1194.             if(debug) printf("Can't create %s; retry #%hu\n",s,tries);
  1195.             goto ReTry;
  1196.         }
  1197.         fprintf(stderr,"\nCouldn't open `%s'\n",s);
  1198.         exit(2);
  1199.     }
  1200.     setmode(handle,O_BINARY);
  1201.  
  1202.     _write(handle,&msg,sizeof(struct _msg));
  1203.  
  1204.     sprintf(s,"\01MSGID: %u:%u/%01u.%01u %8.8s\r",myzone,mynet,mynode,mypoint,make_msgid());
  1205.     _write(handle,s,strlen(s));        /* MSGID kludge */
  1206.  
  1207.     sprintf(s,"\01MSGTO: %u:%u/%01u.%01u\r",zone,net,node,point);
  1208.     _write(handle,s,strlen(s));        /* MSGTO kludge */
  1209.  
  1210. /* 09/15/90 FLAGS info updated to sorta match that given by Odinn Sorenson */
  1211. /* 12/03/90 FLAGS info updated to match (maybe) FSC-0053 */
  1212.  
  1213.     _write(handle,"\01FLAGS TFS XMA",11);   /* FIL? */
  1214.     if(type=='H') _write(handle," HLD",5);
  1215.     if(type=='C') _write(handle," CRA",6);  /* IMM? */
  1216. /*    if(type=='N' || type=='F' || type=='O') _write(handle," NRM",5); */ /* ???? */
  1217.     if(type=='D') _write(handle," DIR",7);
  1218.     _write(handle,"\r",1);
  1219.  
  1220.     if(mypoint) {   /* Barforama stuff for backward (and I do mean backward) */
  1221.         sprintf(s,"\01FMPT %01u\r",mypoint);    /* compatibility */
  1222.         _write(handle,s,strlen(s));
  1223.     }    /* FMPT kludge */
  1224.  
  1225.     if(point) {
  1226.         sprintf(s,"\01TOPT %01u\r",point);
  1227.         _write(handle,s,strlen(s));
  1228.     }    /* TOPT kludge */
  1229.  
  1230.     if(zone!=myzone) {
  1231.         y=sprintf(s,"\01INTL %u:%u/%01u %u:%u/%01u\r",zone,net,node,myzone,mynet,mynode);
  1232.         _write(handle,s,y);
  1233.     }    /* INTL kludge */
  1234.  
  1235.     sprintf(s,"\01PID: %s\r",PID_ID);
  1236.     _write(handle,s,strlen(s));        /* PID kludge just for the hell of it */
  1237.     _write(handle,"\0",1);            /* Null-terminate (couldn't hoit) */
  1238.  
  1239.     _close(handle);
  1240.  
  1241.     return 0;
  1242. }
  1243.  
  1244.  
  1245. int pascal makearc (char *arcfile,char *pktfile,char *origpkt, char *outbound) {
  1246.  
  1247.     char level;
  1248.     char s[177];
  1249.     struct ffblk f;
  1250.  
  1251.         /* Create/add to a bundle */
  1252.  
  1253.     if(stricmp(arccmd,"DON'T_ARCHIVE")) {    /* Kludge for not archiving w/ *.MSG attaches */
  1254.         sprintf(s,"%s %s %s",arccmd,arcfile,pktfile);
  1255.         if(debug || more) printf("To DOS: %s\n",s);
  1256.         level=spawnit(s);
  1257.         if(findfirst(arcfile,&f,0)) {
  1258. ArchiverError:
  1259.             fprintf(stderr,"\nArchive attempt failed!\n");
  1260.             origpkt[strlen(origpkt)-1]='!';
  1261.             printf("Renaming %s to %s\\%s\n",pktfile,outbound,origpkt);
  1262.             sprintf(s,"%s\\%s",outbound,origpkt);
  1263.             if(rename(pktfile,s)) return -1;
  1264.             return 1;
  1265.         }
  1266.         else if (f.ff_fsize==0L) goto ArchiverError;
  1267.         if(!findfirst(pktfile,&f,0)) {
  1268.             printf("Archiver didn't kill packet.\n");
  1269.             if(!level) {
  1270.                 printf("  I will...\n");
  1271.                 unlink(pktfile);
  1272.             }
  1273.             else {
  1274.                 origpkt[strlen(origpkt)-1]='!';
  1275.                 printf("Renaming %s to %s\\%s...\n",pktfile,outbound,origpkt);
  1276.                 sprintf(s,"%s\\%s",outbound,origpkt);
  1277.                 if(rename(pktfile,s)) return -1;
  1278.                 return 1;
  1279.             }
  1280.         }
  1281.         return 0;
  1282.     }
  1283.  
  1284.     strcpy(arcfile,pktfile);    /* Now attach msg will reference bare
  1285.                                    packet name, not an archive */
  1286.     return 0;
  1287. }
  1288.